/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.kernel;

/**
 * This class define an exception
 * ({@link fr.x9c.cadmium.kernel.Fatal.Exception}) that should not occur
 * if bytecode is both correct and meeting Cadmium's restrictions, as well as
 * means to throw such exceptions.
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.0
 * @since 1.0
 */
public final class Fatal {

    /** Represents the different kinds of fatal errors that may occur. */
    private static enum Kind {

        /** Stack underflow (access to unavailable stack element). */
        STACK_UNDERFLOW("stack underflow"),

            /** Use of a 64-bit element. */
            SIXTY_FOUR_ELEMENT("64-bit elements are not supported");

        /** Error message. */
        private final String msg;

        /**
         * Constructs an instance from a message.
         * @param m message - should not be <tt>null</tt>
         */
        private Kind(final String m) {
            assert m != null : "null m";
            this.msg = m;
        } // end constructor(String)

        /**
         * Returns the message of the error.
         * @return the message of the error
         */
        private String getMsg() {
            return this.msg;
        } // end method 'getMsg()'

    } // end enum 'Kind'

    /**
     * No instance of this class.
     */
    private Fatal() {
    } // end empty constructor

    /**
     * Throws a {@link fr.x9c.cadmium.kernel.Fatal.Exception}.
     * @param k kind of error to throw - should not be <tt>null</tt>
     * @throws Fatal.Exception always
     */
    private static void raise(final Kind k) throws Fatal.Exception {
        assert k != null : "null k";
        throw new Fatal.Exception(k);
    } // end method 'raise(Kind)'

    /**
     * Throws a {@link fr.x9c.cadmium.kernel.Fatal.Exception}.
     * @param msg message of exception
     * @throws Fatal.Exception always
     */
    public static void raise(final String msg) throws Fatal.Exception {
        assert msg != null : "null msg";
        throw new Fatal.Exception(msg);
    } // end method 'raise(String)'

    /**
     * To be called when a stack underflow occurs.
     * @throws Fatal.Exception always
     */
    public static void raiseStackUnderflow() throws Fatal.Exception {
        raise(Fatal.Kind.STACK_UNDERFLOW);
    } // end method 'raiseStackUnderflow()'

    /**
     * To be called when a 64-bit element is encountered.
     * @throws Fatal.Exception always
     */
    public static void raise64bitElement() throws Fatal.Exception {
        raise(Fatal.Kind.SIXTY_FOUR_ELEMENT);
    } // end method 'raise64bitElement()'

    /**
     * This class represents an exception thrown when a fatal error occurs.
     */
    public static final class Exception extends java.lang.Exception {

        /** Serialization UID. */
        static final long serialVersionUID = -5700066437826884812L;

        /**
         * Constructs an instance from a kind.
         * @param k kind of error
         */
        private Exception(final Kind k) {
            super(k.getMsg());
        } // end constructor(Kind)

        /**
         * Constructs an instance from a string.
         * @param msg exception message
         */
        private Exception(final String msg) {
            super(msg);
        } // end constructor(String)

    } // end inner-class 'Exception'

} // end class 'Fatal'
